package com.zone.core.base

import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import com.zone.core.coroutine.CoroutineLambda
import com.zone.core.coroutine.ErrorHandle
import com.zone.core.coroutine.request
import com.zone.core.model.EVENT_BACK
import com.zone.core.model.Event
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.Dispatchers

open class BaseViewModel : ViewModel() {

    var isLoading = MutableLiveData<Boolean>()
    var hintText = MutableLiveData<Event<String>>()
    var hintTextRes = MutableLiveData<Event<Int>>()
    var event = MutableLiveData<Event<Int>>()

    fun getHintRes(): Int {
        return hintTextRes.value?.getValueIfNotHandled() ?: 0
    }

    fun getEventId(): Int {
        return event.value?.getValueIfNotHandled() ?: -1
    }

    fun getHintText(): String? {
        return hintText.value?.getValueIfNotHandled()
    }

    protected fun postHintText(msg: String) {
        hintText.postValue(Event(msg))
    }

    protected fun postHintText(msgRes: Int) {
        hintTextRes.postValue(Event(msgRes))
    }

    protected fun postEvent(eventId: Int) {
        event.postValue(Event(eventId))
    }

    fun launch(
        type: CoroutineDispatcher = Dispatchers.Main,
        isShowLoading: Boolean = true,
        onError: ErrorHandle? = null,
        block: CoroutineLambda
    ) {
        request(type, error = { t ->
            if (type != Dispatchers.Main) {
                isLoading.postValue(false)
            } else {
                isLoading.value = false
            }
            onError?.invoke(t) == true
        }) {
            if (type != Dispatchers.Main) {
                isLoading.postValue(isShowLoading)
                block()
                isLoading.postValue(false)
            } else {
                isLoading.value = isShowLoading
                block()
                isLoading.value = false
            }

        }
    }

    fun launchIO(
        type: CoroutineDispatcher = Dispatchers.IO,
        isShowLoading: Boolean = true,
        onError: ErrorHandle? = null,
        block: CoroutineLambda
    ) {
        request(type, error = { t ->
            if (type != Dispatchers.Main) {
                isLoading.postValue(false)
            } else {
                isLoading.value = false
            }
            onError?.invoke(t) == true
        }) {
            if (type != Dispatchers.Main) {
                isLoading.postValue(isShowLoading)
                block()
                isLoading.postValue(false)
            } else {
                isLoading.value = isShowLoading
                block()
                isLoading.value = false
            }

        }
    }

    fun back() {
        postEvent(EVENT_BACK)
    }

}
